﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nini.Config;
using System.IO;
using System.Windows;

namespace MBO_PIM
{
    class LevenshteinMatrix
    {
        private static LevenshteinMatrix lm;
        private int MAX_DISTANCE = 2;
        private IniConfigSource gestureList;
        private string savePath = "./gestures.ini";

        private LevenshteinMatrix() {
            try
            {
                gestureList = new IniConfigSource(this.savePath);
            }
            catch (FileNotFoundException e)
            {
                gestureList = new IniConfigSource();
                gestureList.Configs.Add("gestures");
                this.addGesture("_S_N", Gesten.T_LISTE);
                this.addGesture("_S_E_N_W", Gesten.T_ANLEGEN);
                this.addGesture("_W", Gesten.MONAT_ZURUECK);
                this.addGesture("_E", Gesten.MONAT_VOR);
                this.addGesture("_SE_W_NE", Gesten.ENDE);
                this.addGesture("_S_E_N", Gesten.HILFE);
            }
        }

        static public LevenshteinMatrix getInstance()
        {
            if (lm == null)
                lm = new LevenshteinMatrix();
            return lm;
        }

        internal void addGesture(string gesture, string action)
        {
            gestureList.Configs["gestures"].Set(gesture, action);
        }

        public string calculate(string gesture) {
            string[] gestures = gestureList.Configs["gestures"].GetKeys();

            int distance = -1;
            string finalGesture = "";
            for (int i = 0; i < gestures.Length; i++)
            {
                int d = 0;
                try
                {
                    d = getDistance(gesture, gestures[i]);
                }catch (IndexOutOfRangeException){};

                if (d <= MAX_DISTANCE && (distance < 0 || distance > d))
                {
                    distance = d;
                    finalGesture = gestures[i];
                }
            }
            return finalGesture.Length>0? gestureList.Configs["gestures"].Get(finalGesture) : null;
        }

        private int getDistance(string gesture, string validgesture)
        {
            int[,] matrix = new int[gesture.Length, validgesture.Length];

            for (int i = 0; i < gesture.Length; i++)
                matrix[i, 0] = i;
            for (int j = 0; j < validgesture.Length; j++)
                matrix[0, j] = j;

            for (int i = 1; i < gesture.Length; i++)
            {
                for (int j = 1; j < validgesture.Length; j++)
                {
                    matrix[i, j] = Math.Min(matrix[i - 1, j] + 1, Math.Min(matrix[i, j - 1] + 1, matrix[i - 1, j - 1] + 1 - (gesture[i].Equals(validgesture[j]) ? 1 : 0)));
                }
            }
            return matrix[gesture.Length - 1, validgesture.Length - 1];
        }

        internal void shutdown()
        {
            try
            {
                gestureList.Save(this.savePath);
            }
            catch {}
        }
    }
}
